Skip to content

记录一次前端输入框引发的抖动 Bug 修复

背景

最近接到一个 AI 公文助手输入优化的需求,需要对 UI 进行改版。发现这个表单处的输入框体验非常不好,于是改为了项目中已引用的 Element-UI 组件库中的 EL-Inpt,改完后发现了问题,只要连续的输入就会出现页面抖动的现象。于是我知道了之前为什么不用组件库中的 EL-Inpt 而是自己写了一个不好用的输入框组件了(🤪)。

如图: 右侧表单填写内容,会导致左侧红色框整体都在抖动 img

当然自己重新写一个好用的组件是一个好办法,但是重新造轮子 。。。 也是个好办法。

那还是需要去看下具体是什么原因导致的这个抖动。

问题分析定位

从 HTML5 层进行排查

  1. 第一步:F12 进行 CSS debug ,查看右侧表单输入时,CSS 变化,发现右侧表单宽度未发生异常,但是左侧区域出现了 10px 的抖动

  2. 第二步:怀疑是我们的布局有问题,于是固定右侧的布局宽度以及将左侧布局直接替换为一个 Div,发现还是会抖动。其实前面提到替换为 EL-Inpt 后出现了抖动、那么大概率也就是这个组件引起的原因。

  3. 第三步:大概率确定就是 EL-Inpt 组件出了问题,于是将 EL-Inpt 的布局中最外层的 Div 移除掉 ( EL-Inpt 组件的布局是 Div -> textarea ),发现抖动也消失了。基本确定就是 EL-Inpt 导致的。

  4. 第四步:去 GithubElement-UI仓库看了下 issue 好像没发现类似的问题,看来还是比较不好复现的 🤪,接着大致看了下 EL-Inpt 组件的实现,发现 calcTextareaHeight.js 中在计算动态输入框高度时会在内容变动时新建了一个隐藏的 Textarea 元素用于计算高度,然后又移除掉,感觉这里很可疑,于是准备先从这里下手。

  5. 第五步:继续回到项目中找到 calcTextareaHeight.js 文件

从项目中调式排查

  1. 第六步:项目是基于 Vite 的,为了好验证直接在项目中调试。

    • Element-UInode_modules/element-ui/lib/input.js 文件是打包后的 EL-Inpt 实现,整体阅读性还好,可以参考着 node_modules/element-ui/packages/input 源码进行阅读,将 calcTextareaHeight.js 中的创建的隐藏域的 Textarea 直接移除掉;

    • node_modules/.vite/deps 文件夹下的文件全部删掉(这个是调式的缓存的 chunk 文件,Vite 之所以高效,多半也是因为如此),然后重新刷新项目,Vite 会继续打包缓存 node_modules/element-ui/lib/input.js 文件到 node_modules/.vite/deps 中; 发下此时不在抖动,也发现问题了, 隐藏域的 Textarea 创建时直接挂载到 document 上,然后在进行样式属性的赋值,这导致在挂载到 document 时,Textarea 占据了一些位置导致左侧视图被挤,导致抖动。

    • 继续上面的步骤,这次只是将 隐藏域的 Textarea 进行了隐藏,问题解决; 当然这里也可以设置让它浮动等等其他方式,在创建时不占空间。

解决问题

  1. Hook ?,似乎不是那么方便
  2. Fork 一份 Element-UI 到私有 Git 仓库,然后进行源码修改,再 npm publishnpm 私有仓库 ? 但是这样每次更新组件很麻烦,而且还受网络环境影响
  3. 这里直接仿照 EL-Inpt 实现重新写了一份组件,满足各种各样的需求

Released under the MIT License.